import pygame
import sys
from ship import Ship
from alien import Alien, FastAlien, StrongAlien, ZigzagAlien
from bullet import Bullet, Laser, Missile

# 初始化Pygame
pygame.init()

# 设置屏幕尺寸
screen = pygame.display.set_mode((800, 600))

# 设置游戏标题
pygame.display.set_caption("Alien Invasion")

# 定义颜色
WHITE = (255, 255, 255)

# 加载背景音乐和音效
pygame.mixer.music.load('sounds/background_music.mp3')
bullet_sound = pygame.mixer.Sound('sounds/bullet.wav')
laser_sound = pygame.mixer.Sound('sounds/laser.wav')
bomb_sound = pygame.mixer.Sound('sounds/bomb.wav')
shield_sound = pygame.mixer.Sound('sounds/shield.wav')
explosion_sound = pygame.mixer.Sound('sounds/explosion.wav')
missile_sound = pygame.mixer.Sound('sounds/missile.wav')

# 播放背景音乐
pygame.mixer.music.play(-1)  # -1表示循环播放

def create_fleet(screen, aliens, speed_factor, level, mode):
    """创建外星人群"""
    alien_types = [Alien, FastAlien, StrongAlien, ZigzagAlien]
    alien_width = Alien(screen).rect.width
    available_space_x = 800 - 2 * alien_width
    number_aliens_x = available_space_x // (2 * alien_width)

    # 在生存模式下，增加外星人的生成速度和数量
    if mode == 'survival':
        level += 1  # 每次生成时增加一行

    for row_number in range(level):  # 根据关卡增加行数
        for alien_number in range(number_aliens_x):
            alien_type = alien_types[(row_number + alien_number) % len(alien_types)]
            alien = alien_type(screen)
            alien.rect.x = alien_width + 2 * alien_width * alien_number
            alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
            aliens.add(alien)

def check_fleet_edges(aliens):
    """有外星人到达边缘时采取相应的措施"""
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(aliens)
            break

def change_fleet_direction(aliens):
    """将整群外星人下移，并改变它们的方向"""
    for alien in aliens.sprites():
        alien.rect.y += 10
    for alien in aliens.sprites():
        alien.fleet_direction *= -1

def update_aliens(aliens, ship, stats):
    """检查是否有外星人位于屏幕边缘，并更新整群外星人的位置"""
    check_fleet_edges(aliens)
    aliens.update()

    # 检测外星人和飞船之间的碰撞
    if not ship.shield_active and pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(stats, aliens, bullets)

    # 检查是否有外星人到达屏幕底部
    check_aliens_bottom(aliens, stats)

def ship_hit(stats, aliens, bullets):
    """响应飞船被外星人撞到"""
    if stats.ships_left > 0:
        # 将ships_left减1
        stats.ships_left -= 1

        # 清空外星人列表和子弹列表
        aliens.empty()
        bullets.empty()

        # 创建一群新的外星人，并将飞船放到屏幕底端中央
        create_fleet(screen, aliens, speed_factor, stats.level, stats.mode)
        ship.rect.centerx = screen.get_rect().centerx
        ship.rect.bottom = screen.get_rect().bottom

        # 播放爆炸音效
        explosion_sound.play()

        # 暂停
        pygame.time.wait(1000)
    else:
        stats.game_active = False
        update_high_scores(stats, score)

def check_aliens_bottom(aliens, stats):
    """检查是否有外星人到达屏幕底部"""
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            ship_hit(stats, aliens, bullets)
            break

def update_screen(screen, ship, aliens, bullets, lasers, missiles, score, stats):
    """更新屏幕上的图像，并切换到新屏幕"""
    screen.fill(WHITE)
    ship.blitme()
    aliens.draw(screen)
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    for laser in lasers.sprites():
        laser.draw_laser()
    for missile in missiles.sprites():
        missile.draw_missile()

    # 显示得分
    font = pygame.font.SysFont(None, 48)
    score_image = font.render(f"Score: {score}", True, (30, 30, 30))
    screen.blit(score_image, (20, 20))

    # 显示剩余生命值
    lives_image = font.render(f"Lives: {stats.ships_left}", True, (30, 30, 30))
    screen.blit(lives_image, (20, 60))

    # 显示关卡
    level_image = font.render(f"Level: {stats.level}", True, (30, 30, 30))
    screen.blit(level_image, (20, 100))

    # 显示炸弹数量
    bombs_image = font.render(f"Bombs: {stats.bombs_left}", True, (30, 30, 30))
    screen.blit(bombs_image, (20, 140))

    # 显示激光数量
    lasers_image = font.render(f"Lasers: {stats.lasers_left}", True, (30, 30, 30))
    screen.blit(lasers_image, (20, 180))

    # 显示导弹数量
    missiles_image = font.render(f"Missiles: {stats.missiles_left}", True, (30, 30, 30))
    screen.blit(missiles_image, (20, 220))

    # 显示护盾数量
    shields_image = font.render(f"Shields: {stats.shields_left}", True, (30, 30, 30))
    screen.blit(shields_image, (20, 260))

    # 显示生存时间（仅在生存模式下）
    if stats.mode == 'survival':
        survival_time = (pygame.time.get_ticks() - stats.start_time) // 1000
        time_image = font.render(f"Survival Time: {survival_time}", True, (30, 30, 30))
        screen.blit(time_image, (20, 300))

    # 显示最高分
    high_score_image = font.render(f"High Score: {stats.high_score}", True, (30, 30, 30))
    screen.blit(high_score_image, (20, 340))

    # 显示最长生存时间
    longest_survival_image = font.render(f"Longest Survival: {stats.longest_survival}", True, (30, 30, 30))
    screen.blit(longest_survival_image, (20, 380))

    pygame.display.flip()

def update_high_scores(stats, score):
    """更新最高分和最长生存时间"""
    if score > stats.high_score:
        stats.high_score = score
    if stats.mode == 'survival':
        survival_time = (pygame.time.get_ticks() - stats.start_time) // 1000
        if survival_time > stats.longest_survival:
            stats.longest_survival = survival_time

class GameStats:
    """跟踪游戏的统计信息"""
    def __init__(self, mode='normal'):
        """初始化统计信息"""
        self.game_active = True
        self.ships_left = 3  # 初始生命值
        self.level = 1  # 初始关卡
        self.bombs_left = 3  # 初始炸弹数量
        self.lasers_left = 3  # 初始激光数量
        self.shields_left = 3  # 初始护盾数量
        self.missiles_left = 3  # 初始导弹数量
        self.mode = mode  # 游戏模式
        self.time_limit = 60  # 时间挑战模式的时间限制（秒）
        self.start_time = pygame.time.get_ticks()  # 游戏开始时间
        self.high_score = 0  # 最高分
        self.longest_survival = 0  # 最长生存时间

# 游戏主循环
def run_game():
    # 选择游戏模式
    mode = 'survival'  # 可以是 'normal', 'time_challenge', 'survival'
    stats = GameStats(mode)

    # 创建一艘飞船
    ship = Ship(screen)
    # 创建一个外星人群
    aliens = pygame.sprite.Group()
    speed_factor = 1
    create_fleet(screen, aliens, speed_factor, 1, mode)
    # 创建一个用于存储子弹的编组
    bullets = pygame.sprite.Group()
    # 创建一个用于存储激光的编组
    lasers = pygame.sprite.Group()
    # 创建一个用于存储导弹的编组
    missiles = pygame.sprite.Group()

    # 初始化得分
    score = 0

    while True:
        # 监视键盘和鼠标事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    ship.moving_right = True
                elif event.key == pygame.K_LEFT:
                    ship.moving_left = True
                elif event.key == pygame.K_SPACE:
                    new_bullet = Bullet(screen, ship)
                    bullets.add(new_bullet)
                    bullet_sound.play()
                elif event.key == pygame.K_b and stats.bombs_left > 0:
                    # 使用炸弹
                    stats.bombs_left -= 1
                    score += sum(alien.score_value for alien in aliens)
                    aliens.empty()
                    bomb_sound.play()
                elif event.key == pygame.K_l and stats.lasers_left > 0:
                    # 使用激光
                    stats.lasers_left -= 1
                    new_laser = Laser(screen, ship)
                    lasers.add(new_laser)
                    laser_sound.play()
                elif event.key == pygame.K_m and stats.missiles_left > 0:
                    # 使用导弹
                    stats.missiles_left -= 1
                    new_missile = Missile(screen, ship)
                    missiles.add(new_missile)
                    missile_sound.play()
                elif event.key == pygame.K_s and stats.shields_left > 0:
                    # 激活护盾
                    stats.shields_left -= 1
                    ship.activate_shield()
                    shield_sound.play()
                elif event.key == pygame.K_r and not stats.game_active:
                    # 重启游戏
                    stats.game_active = True
                    stats.ships_left = 3
                    stats.level = 1
                    stats.bombs_left = 3
                    stats.lasers_left = 3
                    stats.shields_left = 3
                    stats.missiles_left = 3
                    aliens.empty()
                    bullets.empty()
                    lasers.empty()
                    missiles.empty()
                    speed_factor = 1
                    create_fleet(screen, aliens, speed_factor, stats.level, mode)
                    ship.rect.centerx = screen.get_rect().centerx
                    ship.rect.bottom = screen.get_rect().bottom
                    score = 0
                    stats.start_time = pygame.time.get_ticks()
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    ship.moving_right = False
                elif event.key == pygame.K_LEFT:
                    ship.moving_left = False

        if stats.game_active:
            # 更新飞船的位置
            ship.update()
            # 更新子弹的位置
            bullets.update()
            # 更新激光的位置
            lasers.update()
            # 更新导弹的位置
            missiles.update()
            # 更新外星人的位置
            update_aliens(aliens, ship, stats)

            # 删除已消失的子弹
            for bullet in bullets.copy():
                if bullet.rect.bottom <= 0:
                    bullets.remove(bullet)

            # 删除已消失的激光
            for laser in lasers.copy():
                if laser.rect.bottom <= 0:
                    lasers.remove(laser)

            # 删除已消失的导弹
            for missile in missiles.copy():
                if missile.rect.bottom <= 0:
                    missiles.remove(missile)

            # 检测子弹和外星人的碰撞
            collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

            # 检测激光和外星人的碰撞
            laser_collisions = pygame.sprite.groupcollide(lasers, aliens, False, True)

            # 检测导弹和外星人的碰撞
            missile_collisions = pygame.sprite.groupcollide(missiles, aliens, True, True)
            if missile_collisions:
                for aliens_hit in missile_collisions.values():
                    for alien in aliens_hit:
                        score += alien.score_value
                        # 爆炸效果：消灭周围的外星人
                        explosion_sound.play()
                        for nearby_alien in aliens:
                            if abs(nearby_alien.rect.x - alien.rect.x) < 50 and abs(nearby_alien.rect.y - alien.rect.y) < 50:
                                aliens.remove(nearby_alien)
                                score += nearby_alien.score_value

            # 更新得分和关卡
            if collisions or laser_collisions:
                for aliens_hit in collisions.values():
                    for alien in aliens_hit:
                        score += alien.score_value
                for aliens_hit in laser_collisions.values():
                    for alien in aliens_hit:
                        score += alien.score_value
                if not aliens:
                    # 如果外星人群被消灭，提升关卡
                    stats.level += 1
                    speed_factor += 0.5
                    create_fleet(screen, aliens, speed_factor, stats.level, mode)

        # 更新屏幕
        update_screen(screen, ship, aliens, bullets, lasers, missiles, score, stats)

# 运行游戏
run_game()
